#pragma once

#include	<Net.h>
#include	<Singleton.h>

/**
 * Communicate with connected client.
 */
class LoginService : public IBaseService, public ISingleton<LoginService> {
public:
	LoginService() : IBaseService("login"), _ver(0), _enable_simple(false), _valid_servers(), _processing() {}
	virtual ~LoginService() {}

	/**
	 * Override close callback to remove processing job.
	 *
	 * \param	sender	Client that closed.
	 * \param	reason	Close reason.
	 */
	virtual void OnClose(Sender * sender, ENet::Close reason) override;

	/**
	 * Implement message processor.
	 *
	 * \param	sender	Client.
	 * \param	msg		Received message from client side.
	 */
	virtual void OnReceive(Sender * sender, Protocol * msg) override;

	/**
	 * Set verify parameter.
	 *
	 * \param	version			Valid client version.
	 * \param	servers			Valid login server ids. For example : "1,2,3"
	 * \param	enable_simple	Is Proto::VT_SIMPLE enabled?
	 */
	void SetVerifyParam(int version, const std::string & servers, bool enable_simple);

	/**
	 * Mark account is in processing.
	 *
	 * \param	account	Processing account.
	 * \param	sender	Connection to find client in future
	 */
	void Link(const std::string & account, Sender * sender);

	/**
	 * Remove processing account.
	 *
	 * \param	account	Processing account.
	 * \param	client	Connection id for find client in future
	 * \return Is this account in processing or not.
	 */
	Sender * Unlink(const std::string & account);

	/**
	 * Send failed verify response to client.
	 *
	 * \param	sender		Client connection.
	 * \param	reason		Failed reason.
	 * \param	serial		Request serial number.
	 * \param	threadsafe	Calling this method in other thread?
	 */
	void FailedVerify(Sender * sender, int reason, uint32_t serial, bool threadsafe = false);

	/**
	 * Send failed create role response to client
	 *
	 * \param	sender	Client connection.
	 * \param	reason	Failed reason.
	 * \param	serial	Request serial number.
	 */
	void FailedCreate(Sender * sender, int reason, uint32_t serial);

private:
	int _ver;
	bool _enable_simple;
	std::map<int, bool> _valid_servers;
	std::map<std::string, uint64_t> _processing;
};
